using Engine.Graphics;
using Engine.Graphics.VertexStructures;
using SharpDX;
using SharpDX.Direct3D11;

namespace ModelViewer
{
    internal class Grid : IRenderableObject
    {
        #region Private Fields

        private Engine.Engine engine;
        private Buffer vb;
        private VertexBufferBinding vertexBufferBinding;
        private BufferDescription vertexBufferDescription;
        private CustomVertex.PositionColored[] vertices;

        #endregion Private Fields

        #region Internal Constructors

        internal Grid(Engine.Engine engine)
        {
            this.engine = engine;
            vertexBufferDescription = new BufferDescription()
            {
                BindFlags = BindFlags.VertexBuffer,
                CpuAccessFlags = 0,
                // OptionFlags = ResourceOptionFlags.BufferStructured,
                SizeInBytes = 0,
                Usage = ResourceUsage.Default
            };
            CreateVertices();

            engine.Grafic.AddRenderableObjects(this, 0);
        }

        #endregion Internal Constructors

        #region Public Methods

        void IRenderableObject.Dispose()
        {
            this.engine.Grafic.RemoveRenderableObject(this);
            if (this.vb != null)
                this.vb.Dispose();
        }

        void IRenderableObject.Render(int renderStep)
        {
            DeviceContext deviceContext = this.engine.Device.ImmediateContext;
            this.engine.Grafic.BlendStateEnableAlpha(true);
            this.engine.Grafic.DepthStateEnableZ(true);

            lock (deviceContext)
            {
                this.engine.Grafic.ShaderManager.SetShader(this.engine.Grafic.ShaderManager.ColorShader);
                deviceContext.InputAssembler.SetVertexBuffers(0, this.vertexBufferBinding);
                deviceContext.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList;
                deviceContext.Draw(this.vertices.Length, 0);
            }
        }

        #endregion Public Methods

        #region Private Methods

        private void CreateVertexBuffer()
        {
            if (this.vb != null)
                vb.Dispose();

            this.vertexBufferDescription.SizeInBytes = CustomVertex.PositionColored.SizeInBytes() * this.vertices.Length;
            lock (this.engine.Device.ImmediateContext)
            {
                this.vb = Buffer.Create(this.engine.Device, vertices, this.vertexBufferDescription);
                this.vertexBufferBinding = new VertexBufferBinding(this.vb, CustomVertex.PositionColored.SizeInBytes(), 0);
            }
        }

        private void CreateVertices()
        {
            float size = 20.0f;
            int count = 20;
            Vector3 position = Vector3.Zero;
            position.Y = -2.0f;

            this.vertices = new CustomVertex.PositionColored[count * 8];
            for (int i = 0; i < count; i++)
            {
                // X-Axis
                position.X = i * size;
                position.Z = -size * count;
                this.vertices[8 * i] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = i * size;
                position.Z = size * count;
                this.vertices[8 * i + 1] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = i * -size;
                position.Z = -size * count;
                this.vertices[8 * i + 2] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = i * -size;
                position.Z = size * count;
                this.vertices[8 * i + 3] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.Blue.ToArgb()));

                // Z-Axis
                position.X = -size * count;
                position.Z = i * size;
                this.vertices[8 * i + 4] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = size * count;
                position.Z = i * size;
                this.vertices[8 * i + 5] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = -size * count;
                position.Z = i * -size;
                this.vertices[8 * i + 6] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.DarkGray.ToArgb()));

                position.X = size * count;
                position.Z = i * -size;
                this.vertices[8 * i + 7] = new CustomVertex.PositionColored(position, new Color4(System.Drawing.Color.Red.ToArgb()));
            }

            CreateVertexBuffer();
        }

        #endregion Private Methods
    }
}